package com.kudian.restful.service;

import com.kudian.common.exception.ApplicationException;
import com.kudian.common.persistence.HibernateDao;
import com.kudian.common.persistence.ResultObj;
import com.kudian.common.service.BaseService;
import com.kudian.common.utils.DateUtils;
import com.kudian.common.utils.PropertiesLoader;
import com.kudian.common.utils.StringUtils;
import com.kudian.restful.dao.*;
import com.kudian.restful.entity.*;
import com.kudian.restful.vo.accountstatement.*;
import org.apache.log4j.Logger;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/7/8.
 */
@Service
@Transactional(readOnly = true)
public class AccountStatementService extends BaseService<AccountStatement, Integer>  {
    private static final Logger logger = Logger.getLogger(AccountStatementService.class);

    @Autowired
    private AccountStatementOrdersDao accountStatementOrdersDao;

    @Autowired
    private AccountStatementDao accountStatementDao;

    @Autowired
    private AccountStatementHisDao accountStatementHisDao;

    @Autowired
    private SellerDao sellerDao;

    @Autowired
    private UsersDao usersDao;

    @Autowired
    private OrderInfoDao orderInfoDao;

    @Autowired
    private LoginSessionDao loginSessionDao;

    @Override
    public HibernateDao<AccountStatement, Integer> getEntityDao() {
        return accountStatementDao;
    }

    @Transactional(readOnly = false)
    public ResultObj add(AccountStatementVO vo) {
        ResultObj o = new ResultObj();
        List<AccountStatementHis> ashs = accountStatementHisDao.find(Restrictions.eq("asDay", vo.getAsDay()));
        if (ashs != null && !ashs.isEmpty()) {
            o.setErrcode(1234);
            o.setErrmsg("当日已经对过账");
            return o;
        }

        AccountStatementHis ash = new AccountStatementHis();
        ash.setAsDay(vo.getAsDay());
        ash.setAddTime(DateUtils.getSysTimestamp());
        accountStatementHisDao.save(ash);

        Timestamp[] days = getDay(vo.getAsDay());
        List<Seller> sellers = this.sellerDao.findbyorder("sellerId", true, Restrictions.eq("sellerStatus", (short)2), Restrictions.ne("gtId", (short)7));
        for (Seller s : sellers) {
            List<OrderInfo> ois = this.orderInfoDao.findbyorder("orderId", false,
                    Restrictions.eq("payStatus", (short)1), Restrictions.eq("sellerId", s.getSellerId()),
                    Restrictions.isNotNull("receivingTime"), Restrictions.between("addTime", days[0], days[1]));

            double ordersAmount = 0;
            for (OrderInfo oi : ois) {
                ordersAmount += oi.getOrderAmount();
            }

            AccountStatement as = new AccountStatement();
            as.setAsDay(vo.getAsDay());
            as.setAddTime(DateUtils.getSysTimestamp());
            as.setAsStatus(true);
            as.setSellerId(s.getSellerId());
            as.setIsPay(false);
            as.setPayTime(null);
            as.setOrdersAmount(ordersAmount);
            double fee = fee(ordersAmount);
            // TODO
            as.setAsAmount(ordersAmount - fee);
            as.setFee(fee);
            as.setIsConfirm(false);
            as.setConfirmTime(null);
            as.setUserId(s.getUserId());
            this.accountStatementDao.save(as);

            for (OrderInfo oi : ois) {
                // ordersAmount += oi.getOrderAmount();
                AccountStatementOrders aso = new AccountStatementOrders();
                aso.setAsId(as.getAsId());
                aso.setOrderId(oi.getOrderId());
                aso.setOrderSn(oi.getOrderSn());
                aso.setOrderAmount(oi.getOrderAmount());

                this.accountStatementOrdersDao.save(aso);
            }
        }

        o.setErrcode(0);
        o.setErrmsg("对账成功");
        return o;
    }

    private Timestamp[] getDay(String asDay) {
        if (StringUtils.isBlank(asDay)) {
            return null;
        }

        String daystart = asDay.substring(0, 4) + "-" + asDay.substring(4, 6) + "-" + asDay.substring(6) + " 00:00:00";
        String dayend = asDay.substring(0, 4) + "-" + asDay.substring(4, 6) + "-" + asDay.substring(6) + " 23:59:59";
        Timestamp[] o = new Timestamp[2];

        o[0] = new Timestamp(DateUtils.parseDate(daystart).getTime());
        o[1] = new Timestamp(DateUtils.parseDate(dayend).getTime());
        return o;
    }

    /**
     * 手续费
     * @return
     */
    private double fee(double ordersAmount) {
        PropertiesLoader loader = new PropertiesLoader("env.properties");
        double fee = loader.getDouble("FEE", 0);

        double ret = ordersAmount * fee;
        BigDecimal bg = new BigDecimal(ret);
        return bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * status : 1:已到账 2:待到账 3:待确认
     * @param vo
     * @return
     */
    public List<AccountStatementItemVO> queryBySeller(QueryAccountStatementBySellerVO vo) {
        List<AccountStatementItemVO> rets = new ArrayList<AccountStatementItemVO>();
        LoginSession ent = loginSessionDao.get(vo.getAccess_token());
        if (ent == null) {
            return null;
        }

        short status;
        if (vo.getStatus() == null) {
            status = 3;
        } else {
            status = vo.getStatus();
        }
        boolean isPay = false;
        boolean isConfirm = false;
        if (status == 3) {
            // 待确认
            isPay = false;
            isConfirm = false;
        } else if (status == 2) {
            isConfirm = true;
            isPay = false;
        } else if (status == 1){
            isConfirm = true;
            isPay = true;
        } else {
            // 待确认
            isPay = false;
            isConfirm = false;
        }
        List<AccountStatement> ass = accountStatementDao.findbyorder("addTime", false,
                Restrictions.eq("userId", ent.getUserId()), Restrictions.eq("asStatus", true),
                Restrictions.eq("isPay", isPay), Restrictions.eq("isConfirm", isConfirm));

        for (AccountStatement as : ass) {
            if (rets == null)
                rets = new ArrayList<AccountStatementItemVO>();

            Seller s = this.sellerDao.get(as.getSellerId());
            AccountStatementItemVO item = new AccountStatementItemVO();
            item.setAsId(as.getAsId());
            String asDay = as.getAsDay();
            asDay = asDay.substring(0,4) + "-" + asDay.substring(4,6) + "-" + asDay.substring(6);
            item.setAsDay(asDay);
            item.setAddTime(as.getAddTime());
            item.setAsStatus(as.getAsStatus());
            item.setSellerId(as.getSellerId());
            item.setSellerName(s.getName());
            item.setIsPay(as.getIsPay());
            item.setPayTime(as.getPayTime());
            item.setAsAmount(as.getAsAmount());
            item.setOrdersAmount(as.getOrdersAmount());
            item.setFee(as.getFee());
            item.setIsConfirm(as.getIsConfirm());
            item.setConfirmTime(as.getConfirmTime());
            item.setUserId(as.getUserId());

            if (as.getIsConfirm()) {
                String accountTip = "预计" + DateUtils.getAfterDate(as.getConfirmTime().getTime(), 4 * 24 * 60 * 60 * 1000) + "到账";
                item.setAccountTip(accountTip);
            }
            List<AccountStatementOrders> asos = this.accountStatementOrdersDao.findbyorder("orderId", true,
                    Restrictions.eq("asId", as.getAsId()));
            if (asos == null || asos.isEmpty()) {
                if (item.getOrders() == null) {
                    item.setOrders(new ArrayList<AccountStatementOrdersItemVO>());
                }
            } else {
                for (AccountStatementOrders aso : asos) {
                    if (item.getOrders() == null) {
                        item.setOrders(new ArrayList<AccountStatementOrdersItemVO>());
                    }

                    AccountStatementOrdersItemVO asoiv = new AccountStatementOrdersItemVO();
                    asoiv.setAsoId(aso.getAsoId());
                    asoiv.setAsId(aso.getAsId());
                    asoiv.setOrderAmount(aso.getOrderAmount());
                    asoiv.setOrderId(aso.getOrderId());
                    asoiv.setOrderSn(aso.getOrderSn());
                    item.getOrders().add(asoiv);
                }
            }
            rets.add(item);
        }
        return rets;
    }

    /**
     * 确认账单
     * @param vo
     * @throws ApplicationException
     */
    @Transactional(readOnly = false)
    public void confirm(ConfirmAccountStatementBySellerVO vo) throws ApplicationException {
        LoginSession ent = loginSessionDao.get(vo.getAccess_token());
        if (ent == null) {
            throw new ApplicationException(9999, "Access_token无效!");
        }
        Seller s = sellerDao.findUnique(Restrictions.eq("userId", ent.getUserId()));
        if (ent == null) {
            throw new ApplicationException(9999, "非商家用户!");
        }

        AccountStatement as = this.accountStatementDao.findUnique(Restrictions.eq("asId", vo.getAsId()),
                Restrictions.eq("sellerId", s.getSellerId()));
        if (as == null) {
            throw new ApplicationException(9999, "此账户无此对账单!");
        }
        as.setConfirmTime(DateUtils.getSysTimestamp());
        as.setIsConfirm(true);
        this.accountStatementDao.save(as);
    }
}
